/*
    rna_structure.cpp. Molecular Biology ++ Implementation file.
    Copyright (C) 2009, 2010, 2011 Daniel Gutson and Martin Gioiosa, FuDePAN

    This file is part of Biopp.

    Biopp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Biopp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Biopp.  If not, see <http://www.gnu.org/licenses/>.

    NOTE: This file is in prototype stage, and is under active development.
*/

#include <stack>
#include <algorithm>
#include <iostream>
#include "biopp/biopp.h"

using namespace std;

namespace biopp
{

void SecStructure::pair(SeqIndex o, SeqIndex c)
{
    if (c < o)
        swap(o, c);

    if (c - o < 4)
        throw(InvalidStructureException("Hairpin loop too small"));
    else if (c >= size())
        throw(InvalidStructureException("Close index out of range"));
    else
    {
        unpair(o);
        unpair(c);
        structure.at(o) = c;
        structure.at(c) = o;
    }
}

void SecStructure::unpair(SeqIndex i)
{
    if (is_paired(i))
    {
        const SeqIndex unpaired = unpaired_value();
        structure.at(structure.at(i)) = unpaired;
        structure.at(i) = unpaired;
    }
}

void SecStructure::set_sequence_size(SeqIndex size)
{
    structure.resize(size, size);
}

SeqIndex SecStructure::paired_with(SeqIndex idx) const
{
    const SeqIndex ret = structure.at(idx);
    assert(ret != unpaired_value());
    return ret;
}

SeqIndex SecStructure::get_prev(SeqIndex i) const
{
    if (i > 0)
        return i - 1;
    else
    {
        if (is_circular())
            return size() - 1;
        else
            throw InvalidStructureException("Out of range");
    }
}

SeqIndex SecStructure::get_next(SeqIndex i) const
{
    if (i < size() - 1)
        return i;
    else
    {
        if (is_circular())
            return 0;
        else
            throw InvalidStructureException("Out of range");
    }
}

}
